package com.xueyi.aixihu.utils;


import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.xueyi.aixihu.config.SpringContextConfig;
import com.xueyi.aixihu.config.WeChatConfig;
import com.xueyi.aixihu.entity.po.AxhFinance;
import com.xueyi.aixihu.entity.vo.*;
import com.xueyi.aixihu.exception.SzException;
import com.xueyi.aixihu.mapper.BindWxMapper;
import com.xueyi.aixihu.status.SystemCode;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.util.CollectionUtils;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate;

import java.nio.charset.StandardCharsets;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @author LuQi
 * @类描述 微信开发工具类
 * @时间 2021/6/20
 */
@Slf4j
public class WeChatDevUtil {

    /**
     * 获取AccessToken的URL
     */
    public static final String ACCESS_TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=";


    public static final String TEMPLATE_URL = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=";

    /**
     * 获取到公众号用户的Open信息
     *
     * @param code      Code
     * @param gzhAppId  公众号的AppId
     * @param gzhSecret 公众号的密钥
     * @return
     */
    public static AccessTokenDefinition getWeChatGzhOpenId(String code, String gzhAppId, String gzhSecret) {

        StringBuffer gzhUrl = new StringBuffer();
        gzhUrl.append("https://api.weixin.qq.com/sns/oauth2/access_token?appid=").append(gzhAppId).append("&secret=").append(gzhSecret).append("&code=").append(code).append("&grant_type=authorization_code");
        String openIds = SpringContextConfig.getBean(RestTemplate.class).getForObject(gzhUrl.toString(), String.class);

        AccessTokenDefinition accessTokenDefinition = null;

        try {
            accessTokenDefinition = JSON.parseObject(openIds, AccessTokenDefinition.class);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }

        if (accessTokenDefinition == null || StringUtils.isEmpty(accessTokenDefinition.getOpenid())) {
            return null;
        }

        return accessTokenDefinition;
    }


    /**
     * 获取公众号操作的assessToken
     *
     * @param gzhAppId
     * @param gzhSecret
     * @return
     */
    public static AccessTokenClass getAssessToken(String gzhAppId, String gzhSecret) {

        // 构建请求的URL
        String requestUrl = ACCESS_TOKEN_URL + gzhAppId + "&secret=" + gzhSecret;
        String requestResp = SpringContextConfig.getBean(RestTemplate.class).getForObject(requestUrl, String.class);

        AccessTokenClass accessTokenClass = JSON.parseObject(requestResp, AccessTokenClass.class);
        if (accessTokenClass == null || (accessTokenClass.getErrcode() != null && accessTokenClass.getErrcode() != 0)) {
            try {
                throw new RuntimeException("微信公众号错误 ," + JSON.toJSONString(accessTokenClass.toString()));
            } catch (Exception e) {
                e.printStackTrace();
                log.warn("获取公众号信息异常：{}", e.getMessage());
            }

        }
        return accessTokenClass;
    }

    public static WxNewsListVo getWxArticleList(String accessToken, String type, Integer offset, Integer count) throws SzException {
        // 构建请求的URL

        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("type", type);
        paramMap.put("offset", offset);
        paramMap.put("count", count);

        StringBuffer requestUrl = new StringBuffer();
        requestUrl.append("https://api.weixin.qq.com/cgi-bin/material/batchget_material?access_token=").append(accessToken);

        RestTemplate restTemplate = SpringContextConfig.getBean(RestTemplate.class);
        restTemplate.getMessageConverters().set(1, new StringHttpMessageConverter(StandardCharsets.UTF_8));
        String requestResp = restTemplate.postForObject(requestUrl.toString(), JSON.toJSONString(paramMap), String.class);
        try {
            WxNewsListVo wxNewsListVo = JSON.parseObject(requestResp, WxNewsListVo.class);
            if (wxNewsListVo.getItem().size() < 1) {
                throw new SzException(SystemCode.QUERY_CHECK_ERROR, "没有可获取内容");
            }
            return wxNewsListVo;

        } catch (Exception e) {
            throw new SzException(SystemCode.QUERY_CHECK_ERROR, "没有可获取内容");
        }


    }

    /**
     * 获取是否关注了公众号
     *
     * @param accessTokenClass
     * @param openId
     * @return
     */
    public static boolean hasCollectService(AccessTokenClass accessTokenClass, String openId) {


        if (accessTokenClass == null) {
            return false;
        }

        String hasGzhURL = "https://api.weixin.qq.com/cgi-bin/user/info?access_token=" + accessTokenClass.getAccess_token() + "&openid=" + openId + "&lang=zh_CN";

        String hasGzhJSON = SpringContextConfig.getBean(RestTemplate.class).getForObject(hasGzhURL, String.class);
        HasCollectService hasCollectService = JSON.parseObject(hasGzhJSON, HasCollectService.class);
        return hasCollectService != null && hasCollectService.getSubscribe() != null && hasCollectService.getSubscribe() == 1;
    }

    /**
     * 微信模版消息的Class
     */
    public static class WeChatTemplate {

        /**
         * 发送财务报表审核提醒
         *
         * @param userId
         */
        public static void sendFinanceReportAuditWarn(Integer userId, String openId, AxhFinance finance, String financeTitle, Integer submitFb, String title,
                                                      Boolean flag) throws SzException {


            log.info("sendFinanceReportAuditWarn: {} , {} , {}", userId, openId, JSON.toJSONString(finance));
            final String templateId = "2hWsjpSRW4ySedXdJ4IPNZILJvejlkQyODsGgUGeE04";
//            final String templateId = "WaFJ6HwpMXv_fA3g80MyGxBFs3vgTpoGNw727oVPlHY";
            String userOpenId = !StringUtils.isEmpty(openId) ? openId : SpringContextConfig.getBean(BindWxMapper.class).findUserOpenId(userId);
            if (StringUtils.isEmpty(userOpenId)) {
                throw new SzException(SystemCode.QUERY_CHECK_ERROR, "该用户并没有绑定微信，请提醒。。。");
            }
            Map<String, TemplateParam> templateParamMap = new HashMap<>();
            // 拼接参数
            templateParamMap.put("first", new TemplateParam("【报表名称】" + financeTitle));
            templateParamMap.put("keyword1", new TemplateParam(DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss")));
            templateParamMap.put("keyword2", new TemplateParam(title));
            templateParamMap.put("remark", new TemplateParam("点我查看详情"));
            try {
                sendWeChatTemplate(templateId, userOpenId, flag ? "http://axh.dfr.cool/axh-mobile/#/pageContent/finance/financialCommunity?userId=" + userId :
                        "http://axh.dfr.cool/axh-mobile/#/pageContent/finance/financeMessage?submitFb=" + submitFb + "&userId=" + userId + "&id=" + finance.getId() + "&from=financialreview&areaName=" + finance.getAreaName(), templateParamMap, null);
            } catch (Exception e) {
                e.printStackTrace();

                // 查看是否是没有关注公众号导致的
                AccessTokenClass assessToken = WeChatDevUtil.getAssessToken(WeChatConfig.WX_GZH_APP_ID, WeChatConfig.WX_GZH_SECRET);
                boolean isCollectWeChat = WeChatDevUtil.hasCollectService(assessToken, userOpenId);
                if (!isCollectWeChat) {
                    throw new SzException(SystemCode.QUERY_CHECK_ERROR, "该用户并没有绑定微信，请提醒。。。");
                }
            }
        }

        /**
         * 发送模版公共方法
         *
         * @param templateId       模版但id
         * @param userWeChatOpenId 用户的openId
         * @param page             跳转的页面
         * @param templateParamMap map
         */
        private static void sendWeChatTemplate(String templateId, String userWeChatOpenId, String page, Map<String, TemplateParam> templateParamMap, String xcxPage) {


            if (StringUtils.isEmpty(templateId) || StringUtils.isEmpty(userWeChatOpenId) || CollectionUtils.isEmpty(templateParamMap)) {
                log.info("发送模版消息失败，参数校验失败,tId_{},oId_{},map_{}", templateId, userWeChatOpenId, templateParamMap);
                return;
            }

            // 收取AccessToken验证
            AccessTokenClass assessToken = getAssessToken(WeChatConfig.WX_GZH_APP_ID, WeChatConfig.WX_GZH_SECRET);

            WxMessageVo wxMessageVo = new WxMessageVo().build(userWeChatOpenId, templateId, page).buildSmallEntity(xcxPage).setData(templateParamMap);

            String templateUrl = TEMPLATE_URL + assessToken.getAccess_token();

            ResponseEntity<String> result = SpringContextConfig.getBean(RestTemplate.class).postForEntity(templateUrl, wxMessageVo, String.class);
            WeChatMsgResult wxMessageResume = JSON.parseObject(result.getBody(), WeChatMsgResult.class);
            log.info("发送公众号模板 {}", wxMessageResume);
        }
    }
}
